﻿// 
//    Copyright 2010 The JaernCloud Project
// 
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
// 
//        http://www.apache.org/licenses/LICENSE-2.0
// 
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.
// 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using JaernCloud.Language.Compiler.Ast;

namespace JaernCloud.Language.Compiler.Types.Builtin {

    public class ConstantNodeType : IConstantNodeType, INodeType {

        private List<string> _names = new List<string>(0);
        private List<INodeType> _children = new List<INodeType>(0);
        private List<INodeType> _references = new List<INodeType>(0);
        private INodeType _parent;
        private AstNode _sourceNode;

        public ConstantNodeType() {

        }

        public ConstantNodeType(AstNode node) {
            this._sourceNode = node;
        }



        #region INodeType

        public string Name {
            get { return String.Empty; }
        }

        public List<string> Names {
            get { return _names; }
        }

        public List<INodeType> Children {
            get { return _children; }
        }

        public List<INodeType> InheritsFrom {
            get { return _references; }
        }

        public INodeType Parent {
            get { return _parent; }
            set { _parent = value; }
        }

        public AstNode SourceNode {
            get { return _sourceNode; }
        }

        public INodeType GetNodeTypeInstanceFor(AstNode node) {
            return new ConstantNodeType(node);
        }

        public bool Equals(INodeType other) {
            if (other is ConstantNodeType) {
                if (!Names.Except(other.Names).Any()) {
                    return SourceNode.Constant.Equals((other as ConstantNodeType).SourceNode.Constant);
                }
            }
            return false;
        }

        #endregion

        public bool IsString {
            get { return SourceNode.Constant is string; }
        }

        public bool IsFloat {
            get { return SourceNode.Constant is float; }
        }

        public bool IsDouble {
            get { return SourceNode.Constant is double; }
        }

        public bool IsBool {
            get { return SourceNode.Constant is bool; }
        }

        public bool IsInt {
            get { return SourceNode.Constant is int; }
        }

        public bool IsLong {
            get { return SourceNode.Constant is long; }
        }

        public bool IsNull {
            get { return SourceNode.Constant is AstConstant && ((AstConstant)SourceNode.Constant == AstConstant.Null); }
        }

        public Type ValueType {
            get { return IsNull ? typeof(void) : SourceNode.Constant.GetType(); }
        }

        public object Value {
            get { return IsNull ? null : SourceNode.Constant; }
        }

        public T ValueAs<T>() {
            if (IsNull) {
                return (T)(object)null;
            }
            return (T)(SourceNode.Constant);
        }

    }
}
